package com.zhuangjie.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhaungjie.base.utils.PasswordGenerator;
import com.zhuangjie.rider.enums.RiderAccountStatus;
import com.zhuangjie.security.entity.AuthenticationTokens;
import com.zhuangjie.security.helper.JwtHelper;
import com.zhuangjie.shop.constant.MerchantAccountConstant;
import com.zhuangjie.shop.dto.LoginDTO;
import com.zhuangjie.shop.entity.MerchantAccount;
import com.zhuangjie.shop.entity.Shop;
import com.zhuangjie.shop.enums.MerchantAccountState;
import com.zhuangjie.shop.enums.ShopMerchantAccountRole;
import com.zhuangjie.shop.helper.ShopModuleTokenDataProvider;
import com.zhuangjie.shop.mapper.MerchantAccountMapper;
import com.zhuangjie.shop.service.MerchantAccountService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 商家账号 服务实现类
 * </p>
 *
 * @author zhuangjie
 * @since 2023-09-24
 */
@Service
@Slf4j
public class MerchantAccountServiceImpl extends ServiceImpl<MerchantAccountMapper, MerchantAccount> implements MerchantAccountService {

    @Resource
    private Redisson redisson;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private JwtHelper jwtHelper;

    @Override
    public MerchantAccount createShopOwnerAccount(Shop shop) {

        // 判断是否已经存在店主账号
        LambdaQueryWrapper<MerchantAccount> queryOwnerAccountWrapper = Wrappers.lambdaQuery(MerchantAccount.class)
                .eq(MerchantAccount::getShopId, shop.getId())
                .eq(MerchantAccount::getIsAdmin, true);
        if (baseMapper.selectOne(queryOwnerAccountWrapper) != null) {
            throw new RuntimeException("店主账号已经存在！");
        }
        // 创建初始化账号信息（默认账号与密码）
        String username = shop.getPhone();
        String password = PasswordGenerator.generate(MerchantAccountConstant.DEFAULT_PASSWORD_LENGTH);

        MerchantAccount shopOwnerInitMerchantAccount = MerchantAccount.builder()
                .name(MerchantAccountConstant.DEFAULT_NAME)
                .phone(shop.getPhone())
                .username(username)
                .password(passwordEncoder.encode(password))
                .status(MerchantAccountState.ENABLE.getValue())
                .isAdmin(1)
                .shopId(shop.getId())
                .build();
        // 插入到数据库
        RLock lock = redisson.getLock("saveShopOwnerInitMerchantAccountLock");
        lock.lock();
        try {
            if (this.baseMapper.insert(shopOwnerInitMerchantAccount) <= 0) {
                throw new RuntimeException("保存店主账号信息失败！");
            }
        }finally {
            // 这里需要加判断再解锁，不然会出现问题,这是Redisson的BUG!
            if(lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        // 再设置回明文密码返回
        shopOwnerInitMerchantAccount.setPassword(password);
        return shopOwnerInitMerchantAccount;
    }

    @Override
    public AuthenticationTokens login(LoginDTO loginDTO) throws Exception {
        LambdaQueryWrapper<MerchantAccount> queryUserWrapper = Wrappers.lambdaQuery(MerchantAccount.class)
                .eq(MerchantAccount::getUsername, loginDTO.getUsername());
        MerchantAccount merchantAccount = this.baseMapper.selectOne(queryUserWrapper);
        if (merchantAccount == null) {
            throw new RuntimeException("用户不存在！");
        }
        if (! passwordEncoder.matches(loginDTO.getPassword(),merchantAccount.getPassword())) {
            throw new RuntimeException("密码不正确！");
        }
        // 生成token
        AuthenticationTokens authenticationTokens = jwtHelper.loginAfterCreateToken((userConfigTokenDateKeys) -> {
            Map<String, Object> tokenData = new HashMap<>();
            tokenData.put(userConfigTokenDateKeys.USER_ID_KEY, merchantAccount.getId());
            tokenData.put(userConfigTokenDateKeys.ROLES_KEY, Arrays.asList(ShopMerchantAccountRole.ADMIN.getValue()));
            // 项目自定义tokenData属性，方便获取根据登录者信息获取其绑定的shopId
            tokenData.put(ShopModuleTokenDataProvider.shopIdKey,merchantAccount.getShopId());
            return tokenData;
        });
        return authenticationTokens;
    }

    @Override
    public AuthenticationTokens refreshToken(String refreshToken) throws Exception {
        // 1. 检查骑手状态
        LambdaQueryWrapper<MerchantAccount> queryRiderIsAvailableWrapper = Wrappers.lambdaQuery(MerchantAccount.class)
                .eq(MerchantAccount::getId, jwtHelper.getTokenOwnerId(refreshToken))
                .ne(MerchantAccount::getStatus, RiderAccountStatus.DISABLE);
        if (this.count(queryRiderIsAvailableWrapper) == 0) {
            throw new RuntimeException("账号已被冻结，无法刷新refreshToken!");
        }
        return jwtHelper.refreshToken(refreshToken);
    }
}
